{$WEAKPACKAGEUNIT ON}

(*:XML helper unit. Contains class to manage shared XML document (stored in the
   resizable shared memory).
   @author Primoz Gabrijelcic
   @desc <pre>
   (c) 2002 Primoz Gabrijelcic
   Free for personal and commercial use. No rights reserved.

   Author            : Primoz Gabrijelcic
   Creation date     : 2002-05-13
   Last modification : 2002-09-24
   Version           : 1.01
</pre>*)(*
   History:
     1.01: 2002-09-24
       - Added property TGpSharedXML.CachedXML.
     1.0: 2002-05-13
       - Created.
*)

unit OmniXMLShared;

interface

uses
  Windows,
  GpSharedMemory,
  OmniXMLProperties;

type
  {:Shared XML document.
  }
  TGpSharedXML = class
  private
    sxOwnsXML     : boolean;
    sxSharedMemory: TGpSharedMemory;
    sxXMLDoc      : TGpXMLDoc;
  protected
    function  Acquire(forWriting: boolean; timeout: DWORD): TGpXMLDoc;
    function  GetName: string;
    function  GetXML: TGpXMLDoc;
  public
    constructor Create(sharedMemoryName: string; xmlDoc: TGpXMLDoc;
      maxSize: cardinal; ownsXML: boolean = true); virtual;
    destructor  Destroy; override;
    function  BeginUpdate(timeout: DWORD): TGpXMLDoc; virtual;
    procedure EndUpdate; virtual;
    function  Read(timeout: DWORD): TGpXMLDoc; virtual;
    property  CachedXML: TGpXMLDoc read sxXMLDoc;
    property  Name: string read GetName;
    property  XML: TGpXMLDoc read GetXML;
  end; { TGpSharedXML }

  {:Shared XML list.
  }
  TGpSharedXMLList = class(TGpSharedXML)
  public
    constructor Create(sharedMemoryName: string; xmlList: TGpXMLDocList;
      maxSize: cardinal; ownsXML: boolean = true); reintroduce; virtual;
    function Count: integer;
  end; { TGpSharedXMLList }

implementation

uses
{$IFDEF DebugXML}
  OmniXMLUtils,
  uDbg,
{$ENDIF DebugXML}
  SysUtils;

{ TGpSharedXML }

function TGpSharedXML.Acquire(forWriting: boolean;
  timeout: DWORD): TGpXMLDoc;
begin
  Result := nil;
  if sxSharedMemory.AcquireMemory(forWriting, timeout) <> nil then begin
      if (not sxSharedMemory.Modified) or
         sxXMLDoc.LoadFromStream(sxSharedMemory.AsStream)
      then
        Result := sxXMLDoc;
    if not assigned(Result) then
      sxSharedMemory.ReleaseMemory;
    {$IFDEF DebugXML}
    if assigned(Result) then
      Debugger.LogFmtMsg('Acquire: %s',[XMLSaveToString(sxXMLDoc.XMLDoc)]);
    {$ENDIF DebugXML}
  end;
end; { TGpSharedXML.Acquire }

function TGpSharedXML.BeginUpdate(timeout: DWORD): TGpXMLDoc;
begin
  Result := Acquire(true, timeout);
end; { TGpSharedXML.BeginUpdate }

constructor TGpSharedXML.Create(sharedMemoryName: string; xmlDoc: TGpXMLDoc;
  maxSize: cardinal; ownsXML: boolean);
begin
  inherited Create;
  sxSharedMemory := TGpSharedMemory.Create(sharedMemoryName, 0, maxSize);
  sxXMLDoc := xmlDoc;
  sxOwnsXML := ownsXML;
end; { TGpSharedXML.Create }

destructor TGpSharedXML.Destroy;
begin
  if sxOwnsXML then
    FreeAndNil(sxXMLDoc)
  else
    sxXMLDoc := nil;
  FreeAndNil(sxSharedMemory);
  inherited;
end; { TGpSharedXML.Destroy }

procedure TGpSharedXML.EndUpdate;
begin
  {$IFDEF DebugXML}
  Debugger.LogFmtMsg('Release: %s',[XMLSaveToString(sxXMLDoc.XMLDoc)]);
  {$ENDIF DebugXML}
  if sxSharedMemory.IsWriting then 
    sxXMLDoc.SaveToStream(sxSharedMemory.AsStream);
  if sxSharedMemory.Acquired then
    sxSharedMemory.ReleaseMemory;
end; { TGpSharedXML.EndUpdate }

function TGpSharedXML.GetName: string;
begin
  Result := sxSharedMemory.Name;
end; { TGpSharedXML.GetName }

function TGpSharedXML.GetXML: TGpXMLDoc;
begin
  if not sxSharedMemory.Acquired then
    Result := nil
  else
    Result := sxXMLDoc;
end; { TGpSharedXML.GetXML }

function TGpSharedXML.Read(timeout: DWORD): TGpXMLDoc;
begin
  Result := Acquire(false, timeout);
  EndUpdate;
end; { TGpSharedXML.Read }

{ TGpSharedXMLList }

function TGpSharedXMLList.Count: integer;
begin
  Result := (XML as TGpXMLDocList).Count;
end; { TGpSharedXMLList.Count }

constructor TGpSharedXMLList.Create(sharedMemoryName: string;
  xmlList: TGpXMLDocList; maxSize: cardinal; ownsXML: boolean);
begin
  inherited Create(sharedMemoryName, xmlList, maxSize, ownsXML);
end; { TGpSharedXMLList.Create }

{$IFDEF DebugXML}
initialization
  NxStartDebug;
finalization
  NxEndDebug;
{$ENDIF DebugXML}
end.
